package com.yc.myfiltersfactory;


import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 移动端访问网关过滤器工厂
 * 用于限制只有移动设备才能访问特定路由
 */
@Component
public class MobileAccessGatewayFilterFactory extends AbstractGatewayFilterFactory<MobileAccessGatewayFilterFactory.Config> {

    // 移动端User-Agent匹配正则表达式
    // 匹配android/iphone/ipad/ipod/blackberry/windows phone/mobile等关键词
    private static final Pattern MOBILE_PATTERN = Pattern.compile(
            ".*(android|iphone|ipad|ipod|blackberry|windows phone|mobile).*",
            Pattern.CASE_INSENSITIVE
    );

    public MobileAccessGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("enabled");
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            // 如果过滤器未启用，直接放行请求
            if (!config.isEnabled()) {
                return chain.filter(exchange);
            }
            // 获取请求头中的User-Agent信息
            String userAgent = exchange.getRequest().getHeaders().getFirst("User-Agent");
            // 如果User-Agent存在且匹配移动设备规则，放行请求
            if (StringUtils.hasText(userAgent) && isMobileUserAgent(userAgent)) {
                return chain.filter(exchange);
            }

            // 非移动端访问，返回403 + 提示
            return denyAccess(exchange);
        };
    }

    /**
     * 判断User-Agent是否来自移动设备
     * @param userAgent 用户代理字符串
     * @return 如果是移动设备返回true，否则返回false
     */
    private boolean isMobileUserAgent(String userAgent) {
        return MOBILE_PATTERN.matcher(userAgent).matches();
    }

    /**
     * 拒绝访问的处理方法
     * @param exchange 服务器网络交换对象
     * @return 返回包含错误信息的响应
     */
    private Mono<Void> denyAccess(ServerWebExchange exchange) {
        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
        exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);

        String body = "{\"error\": \"Access denied: Only mobile devices are allowed.\"}";
        byte[] bytes = body.getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);

        return exchange.getResponse().writeWith(Mono.just(buffer));
    }

    public static class Config {
        private boolean enabled = true;

        public boolean isEnabled() {
            return enabled;
        }

        public Config setEnabled(boolean enabled) {
            this.enabled = enabled;
            return this;
        }
    }
}
